#include<iostream>
#include<stdexcept>
#include<cstring>
#include<cstdlib>

////����4.1��˳�������˼�����ֵ�������̵� �������졢��ֵ�������ȵ������
// 
////�ܱ�ѧϰ
//// malloc����Ҫ�������ڶ��ڴ��з���һ��ָ����С�������ڴ�ռ䡣
//// 
//// realloc���ڵ����Ѿ�ͨ��malloc��calloc��realloc������ڴ���С��
//// �ȿ�������Ҳ����Сԭ���ڴ�飬������ԭ�ڴ�λ����չ�����еĻ��Ͱ����ݸ��Ƶ���λ�ã����ͷž��ڴ档
//
//template<typename T>
//class my_vector
//{
//  T* array;
//  unsigned size;
//  unsigned block_size;
//public:
//  my_vector(unsigned bsz):
//    array((T*)malloc(sizeof(T)*bsz)), size(0), block_size(bsz)
//  {
//      if (array)
//      {
//          memset(array, 0, bsz * sizeof(T));
//      }
//  }
//  ~my_vector() { if (array) free(array); }//����free��delete���������ﲻ����delete�Ƿ������⣬���忴����Ԫ�ص�ʱ��ĸ�ֵ������ test
//
//  void push_back(T const& elem) {
//    if (size == block_size)
//    {//���еĿռ������꣬��Ҫ�������ռ�
//      block_size *= 2;
//      T* new_array = (T*)realloc(array, block_size * sizeof(T));
//      if (new_array) array = new_array;
//      else {
//        //����ʧ�ܣ��ڴ�ľ�
//        free(array);
//        array = nullptr;
//        throw std::runtime_error("Out of memory.");
//      }
//    }
//    array[size++] = elem; //��ֵ ԭ�ж����������
//  }
//
//  T& operator[](unsigned i) { return array[i]; }
//  const T& operator[](unsigned i)const { return array[i]; }
//
//  //ռ���˶����ڴ�
//  unsigned get_mem_size()const { return block_size * sizeof(T); }
//};
//
//class TestData {
//public:
//  const static int InitIVValue = 999;
//  const static int MemoryTestSize = 10;
//  int iv_{ InitIVValue };
//  char* memory_manage_{nullptr};
//  ~TestData() {
//    std::cout << "run in TestData destructor" << std::endl;
//    delete[] memory_manage_; //�����ж��Ƿ�Ϊnullptr
//  }
//  TestData(const TestData& obj):iv_(obj.iv_){
//    std::clog << "run in TestData copy constructor" << std::endl;
//    //memory_manage_ = nullptr;//�����涨��ʱ����б���ʼ������䲻��Ҫ
//    if (obj.memory_manage_)
//    {
//        memory_manage_ = new char[MemoryTestSize];
//        memcpy(memory_manage_, obj.memory_manage_, MemoryTestSize);
//    }
//  }
//  TestData& operator=(const TestData& obj) {
//    std::cout << "run in TestData operator= fun" << std::endl;
//    if (this == &obj) {
//      return *this;
//    }
//    iv_ = obj.iv_;
//    if (memory_manage_)
//    {
//        delete[] memory_manage_;
//        memory_manage_ = nullptr;
//    }
//    if (obj.memory_manage_)
//    {
//        memory_manage_ = new char[MemoryTestSize];
//        memcpy(memory_manage_, obj.memory_manage_, MemoryTestSize);
//    }
//    return *this;
//  }
//  TestData() = default;
//
//};
//
//void funTestVectorAssignGet() {
//    my_vector<TestData> vtData(3);// memory_manage_ Ҳ�� 0xcdcdcdcd����Ϊ�ߵ�malloc��û�߳�ʼ��������̣������⣡����
//    TestData objGet = vtData[0];// һ�ο������졣{iv_=0xcdcdcdcd },����InitIVValue��
//    objGet = vtData[1];         // һ�θ�ֵ������
//
//    TestData toPushObj; // һ��Ĭ�Ϲ��죬  ��InitIVValue
//    vtData.push_back(toPushObj);// �ڲ�һ�θ�ֵ������
//    objGet = vtData[0];// һ�θ�ֵ�������� ��InitIVValue
//}// objGet��toPushObj ��������������� my_vector ���û�гɹ�����
//
//void funTestVectorDestruct() {
//    my_vector<TestData> vtData(3);
//    //vtData[0] = TestData(); //��ʱ����Ĭ�Ϲ��죬��ֵ��������ʱ ��������
//   // vtData[1] = TestData{3, nullptr};
//}//my_vector �е���������û�д�������������������������Ҫ�ͷ��ڴ�Ķ����������ȱʧ��й©
//
//int run_main_eg4_1()
//{
//  my_vector<int> vt(3);
//  vt.push_back(10);
//
//  //funTestVectorAssignGet();
//  funTestVectorDestruct();
//  return 0;
//}


// ��4.2
template<typename T>
class my_vector
{
    T* array{};
    unsigned size{ 0 };
    unsigned block_size{ 0 };
public:
    my_vector(unsigned bsz) :
        array((T*)malloc(sizeof(T)* bsz)), size(0), block_size(bsz)
    {
		if (array)
		{
			memset(array, 0, bsz * sizeof(T));
		}
    }
    ~my_vector() { if (array) free(array); }//����free��delete���������ﲻ����delete�Ƿ������⣬���忴����Ԫ�ص�ʱ��ĸ�ֵ������ test

    void push_back(T const& elem) {
        if (size == block_size)
        {//���еĿռ������꣬��Ҫ�������ռ�
            block_size *= 2;
            T* new_array = (T*)realloc(array, block_size * sizeof(T));
            if (new_array) array = new_array;//��������ռ��е� �ڴ��δʼ������
            else {
                //����ʧ�ܣ��ڴ�ľ�
                free(array);
                array = nullptr;
                throw std::runtime_error("Out of memory.");
            }
        }
        array[size++] = elem; //��ֵ ԭ�ж����������
    }

    T& operator[](unsigned i) { return array[i]; }
    const T& operator[](unsigned i)const { return array[i]; }

    //ռ���˶����ڴ�
    unsigned get_mem_size()const { return block_size * sizeof(T); }
};

template<>
class my_vector<bool>
{
    int* array{};
    unsigned size{ 0 };
    unsigned block_size{ 0 };
    //const static unsigned seg_size;// = sizeof(int) * 8;
    const static unsigned seg_size = sizeof(int) * 8;
public:
    int idd_attr_test{ 777 }; //�ػ��������� �����ֶβ���
    my_vector(unsigned bsz = 1):
        array((int*)malloc(sizeof(int) * bsz)),
        size(0), block_size(bsz)
    {}//memset(array, 0, bsz * sizeof(int));
    ~my_vector() { if (array) free(array); }

    void push_back(bool elem) {
        if (size == block_size * seg_size)
        {
            block_size *= 2;
            int* new_array = (int*)realloc(array, block_size * sizeof(int));
            if (new_array) array = new_array;
            else {
                free(array);
                array = nullptr;
                throw std::runtime_error("Out of memory.");
            }
        }
        set(size++, elem);
    }
    void set(unsigned i, bool elem) {
        if (elem) {
            array[i / seg_size] |= (0x1 << (i % seg_size));
        }
        else {
            array[i / seg_size] &= ~(0x1 << (i % seg_size));
        }
    }
    bool operator[](unsigned i)const {
        return (array[i / seg_size] & (0x1 << (i % seg_size))) != 0;// lnt - comparison - bitwise - precedence	�Ƚ�����������ȼ����ڰ�λ�������
    }
    unsigned get_mem_size()const { return block_size * sizeof(int); }// ����ػ��汾���в����£�����ʱ�ᱨ�������ȱʧ��δ���ã������������еģ��� error C2039: "get_mem_size": ���� "my_vector<bool>" �ĳ�Ա��
};
//const unsigned my_vector<bool>::seg_size = sizeof(int) * 8;

int run_main_eg4_2()
{
    char chVtttt = 'x';
    my_vector<decltype(chVtttt)> vi(2);
    my_vector<char> vii(2);
    my_vector<bool> vb(2);
    for (unsigned i = 0; i < 20; ++i) {
        vi.push_back('a' + i);
        vb.push_back((i % 4) == 0);
    }
    using namespace std;
    cout << "MemSize of my_vector<char> is " << vi.get_mem_size() << endl;
    cout << "MemSize of my_vector<bool> is " << vb.get_mem_size() << endl;
    for (unsigned i = 0; i < 20; ++i)
        cout << ' ' << vi[i];
    cout << endl;
    for (unsigned i = 0; i < 20; ++i)
        cout << ' ' << vb[i];
    cout << endl;
//MemSize of my_vector<char> is 32
//MemSize of my_vector<bool> is 8
// a b c d e f g h i j k l m n o p q r s t
// 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0
    cout << vb.idd_attr_test << endl;//777
    return 0;
}

int main() {
    return run_main_eg4_2();
}
//���ģ����Ӧ�û��������Ƶ� free��new�����Ե����⣬֮ǰ4.1��Ҳ����֤�ˣ�4.2�Ͳ��������پ����ˣ�������Ҫѧϰ����ϤЩģ��֪ʶ�ͺ���
